package com.qiniu.aiplayroles.controller;

import com.qiniu.aiplayroles.app.PlayApp;
import com.qiniu.aiplayroles.model.RoleCard;
import com.qiniu.aiplayroles.service.PromptService;
import com.qiniu.aiplayroles.service.RoleService;
import com.qiniu.aiplayroles.service.VoiceService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.*;
import java.util.Base64;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
@Slf4j
public class RoleController {

    private final RoleService roleService;
    private final PromptService promptService;
    private final PlayApp playApp;
    private final VoiceService voiceService;

    @GetMapping("/roles")
    public ResponseEntity<List<RoleCard>> listRoles() {
        return ResponseEntity.ok(roleService.getAllRoles());
    }

    @GetMapping("/roles/search")
    public ResponseEntity<List<RoleCard>> searchRoles(
            @RequestParam(value = "keyword", required = false) String keyword) {
        return ResponseEntity.ok(roleService.searchRoles(keyword));
    }

    @GetMapping("/roles/{roleId}")
    public ResponseEntity<RoleCard> getRole(@PathVariable String roleId) {
        RoleCard role = roleService.getRoleById(roleId);
        if (role == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(role);
    }

    @PostMapping("/roles/{roleId}/chat")
    public ResponseEntity<ChatResponse> chatWithRoleSYNC(@PathVariable String roleId, @RequestBody ChatRequest req) {
        if (req == null || req.getMessage() == null || req.getMessage().trim().isEmpty()) {
            return ResponseEntity.badRequest().build();
        }
        RoleCard role = roleService.getRoleById(roleId);
        if (role == null) {
            return ResponseEntity.notFound().build();
        }

        // 使用通用模板渲染 system prompt（overrides 可以为 null）
        String systemPrompt = promptService.render(role, req.getOverrides());

        // 如果启用了技能，在system prompt前添加技能提示词
        if (req.getUseSkill() != null && req.getUseSkill() && role.getSkillPromptTemplate() != null) {
            systemPrompt = role.getSkillPromptTemplate() + "\n\n" + systemPrompt;
        }
        String chatId = (req.getChatId() == null || req.getChatId().isEmpty())
                ? UUID.randomUUID().toString()
                : req.getChatId();

        String content = playApp.doChat(req.getMessage(), chatId, systemPrompt);
        ChatResponse resp = new ChatResponse();
        resp.setChatId(chatId);
        resp.setContent(content);
        return ResponseEntity.ok(resp);
    }

    /**
     * SSE 流式聊天接口
     * 
     * @param roleId  角色ID
     * @param message 用户消息
     * @param chatId  会话ID（可选）
     * @return SseEmitter
     */
    @GetMapping("/roles/{roleId}/chat/sse")
    public SseEmitter doChatWithRoleSseEmitter(
            @PathVariable String roleId,
            @RequestParam String message,
            @RequestParam(required = false) String chatId,
            @RequestParam(required = false) Boolean useSkill) {

        // 验证角色是否存在
        RoleCard role = roleService.getRoleById(roleId);
        if (role == null) {
            SseEmitter errorEmitter = new SseEmitter(5000L);
            try {
                errorEmitter.send("角色不存在");
                errorEmitter.complete();
            } catch (IOException e) {
                errorEmitter.completeWithError(e);
            }
            return errorEmitter;
        }

        // 创建 SseEmitter，设置3分钟超时
        SseEmitter emitter = new SseEmitter(180000L);

        // 准备 overrides（暂时未使用，保留用于未来扩展）
        // Map<String, Object> overrides = new HashMap<>();

        // 渲染 system prompt
        String systemPrompt = promptService.render(role, null);

        // 如果启用了技能，在system prompt前添加技能提示词
        if (useSkill != null && useSkill && role.getSkillPromptTemplate() != null) {
            systemPrompt = role.getSkillPromptTemplate() + "\n\n" + systemPrompt;
        }

        // 生成 chatId（如果未提供）
        String finalChatId = (chatId == null || chatId.isEmpty())
                ? UUID.randomUUID().toString()
                : chatId;

        // 用于累积完整的回复文本
        StringBuilder fullResponse = new StringBuilder();

        // 获取流式数据并订阅
        playApp.doChatByStream(message, finalChatId, systemPrompt)
                .subscribe(
                        // 处理每条消息
                        chunk -> {
                            try {
                                // 累积文本用于语音合成
                                fullResponse.append(chunk);
                                emitter.send(chunk);
                            } catch (IOException e) {
                                emitter.completeWithError(e);
                            }
                        },
                        // 处理错误
                        error -> {
                            log.error("SSE流式输出错误: {}", error.getMessage(), error);
                            emitter.completeWithError(error);
                        },
                        // 处理完成 - 文本输出完成后开始语音合成
                        () -> {
                            try {
                                String completeText = fullResponse.toString().trim();
                                log.info("文本输出完成，开始语音合成。文本长度: {}", completeText.length());

                                if (!completeText.isEmpty()) {
                                    // 发送语音合成开始的信号
                                    emitter.send(SseEmitter.event()
                                            .name("voice-start")
                                            .data("开始语音合成..."));

                                    // 异步进行语音合成，使用角色卡中指定的音色
                                    String roleVoice = role.getVoice();
                                    voiceService.synthesizeSpeech(completeText, roleVoice)
                                            .subscribe(
                                                    audioData -> {
                                                        try {
                                                            log.info("准备发送音频数据，大小: {} bytes", audioData.length);

                                                            // 将音频数据转换为Base64编码
                                                            String base64Audio = Base64.getEncoder()
                                                                    .encodeToString(audioData);
                                                            log.info("Base64编码完成，长度: {}", base64Audio.length());

                                                            // 发送音频数据（Base64编码）
                                                            emitter.send(SseEmitter.event()
                                                                    .name("voice-data")
                                                                    .data(base64Audio));

                                                            // 发送语音合成完成信号
                                                            emitter.send(SseEmitter.event()
                                                                    .name("voice-complete")
                                                                    .data("语音合成完成"));

                                                            // 完成SSE连接
                                                            emitter.complete();
                                                        } catch (IOException e) {
                                                            log.error("发送音频数据失败: {}", e.getMessage(), e);
                                                            emitter.completeWithError(e);
                                                        }
                                                    },
                                                    voiceError -> {
                                                        log.error("语音合成失败: {}", voiceError.getMessage(), voiceError);
                                                        try {
                                                            emitter.send(SseEmitter.event()
                                                                    .name("voice-error")
                                                                    .data("语音合成失败: " + voiceError.getMessage()));
                                                        } catch (IOException e) {
                                                            // 忽略发送错误信息的异常
                                                        }
                                                        emitter.completeWithError(voiceError);
                                                    });
                                } else {
                                    // 不启用语音合成，直接完成
                                    emitter.complete();
                                }
                            } catch (Exception e) {
                                log.error("完成SSE流时发生错误: {}", e.getMessage(), e);
                                emitter.completeWithError(e);
                            }
                        });

        return emitter;
    }

    /**
     * 测试语音合成接口 - 简单GET请求
     * 
     * @param text  要合成的文本
     * @param voice 音色（可选，默认使用longxiaochun_v2）
     * @return 音频数据
     */
    @GetMapping("/voice/test")
    public ResponseEntity<?> testVoiceSynthesis(
            @RequestParam String text,
            @RequestParam(required = false) String voice) {
        try {
            if (text == null || text.trim().isEmpty()) {
                return ResponseEntity.badRequest().body("文本不能为空");
            }

            log.info("测试语音合成 - 文本: '{}', 音色: '{}'", text, voice);

            return voiceService.synthesizeSpeech(text, voice)
                    .map(audioData -> {
                        log.info("语音合成成功，音频数据大小: {} bytes", audioData.length);
                        // 返回音频数据，设置正确的Content-Type
                        return ResponseEntity.ok()
                                .header("Content-Type", "audio/mpeg")
                                .header("Content-Length", String.valueOf(audioData.length))
                                .body(audioData);
                    })
                    .cast(ResponseEntity.class)
                    .onErrorResume(error -> {
                        log.error("语音合成失败: {}", error.getMessage(), error);
                        return Mono.just(ResponseEntity.internalServerError()
                                .body("语音合成失败: " + error.getMessage()));
                    })
                    .block(); // 这里使用block()因为需要同步返回ResponseEntity
        } catch (Exception e) {
            log.error("语音合成接口异常: {}", e.getMessage(), e);
            return ResponseEntity.internalServerError()
                    .body("语音合成失败: " + e.getMessage());
        }
    }

    /**
     * 单独的语音合成接口
     * 
     * @param text  要合成的文本
     * @param voice 音色（可选，默认使用longxiaochun_v2）
     * @return 音频数据
     */
    @PostMapping("/voice/synthesize")
    public ResponseEntity<?> synthesizeVoice(@RequestBody VoiceRequest request) {
        try {
            if (request.getText() == null || request.getText().trim().isEmpty()) {
                return ResponseEntity.badRequest().body("文本不能为空");
            }

            return voiceService.synthesizeSpeech(request.getText(), request.getVoice())
                    .map(audioData -> {
                        // 返回音频数据，设置正确的Content-Type
                        return ResponseEntity.ok()
                                .header("Content-Type", "audio/mpeg")
                                .header("Content-Length", String.valueOf(audioData.length))
                                .body(audioData);
                    })
                    .cast(ResponseEntity.class)
                    .onErrorResume(error -> {
                        log.error("语音合成失败: {}", error.getMessage(), error);
                        return Mono.just(ResponseEntity.internalServerError()
                                .body("语音合成失败: " + error.getMessage()));
                    })
                    .block(); // 这里使用block()因为需要同步返回ResponseEntity
        } catch (Exception e) {
            log.error("语音合成接口异常: {}", e.getMessage(), e);
            return ResponseEntity.internalServerError()
                    .body("语音合成失败: " + e.getMessage());
        }
    }

    @Data
    public static class VoiceRequest {
        private String text;
        private String voice;
    }

    @Data
    public static class ChatRequest {
        private String message;
        private String chatId;
        private Map<String, Object> overrides; // 可选：覆盖模板变量，如 language/max_tokens_per_reply
        private Boolean useSkill; // 是否使用角色技能
    }

    @Data
    public static class ChatResponse {
        private String chatId;
        private String content;
    }
}